/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "movement_service.h"

#include <ipc_skeleton.h>
#include "if_system_ability_manager.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"

#include "movement_permission.h"
#include "movement_common.h"

namespace OHOS {
namespace Msdp {
namespace {
auto ms = DelayedSpSingleton<MovementService>::GetInstance();
const bool G_REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(ms.GetRefPtr());
constexpr int32_t MAX_DMUP_PARAM = 2;
}
MovementService::MovementService() : SystemAbility(MSDP_MOVEMENT_SERVICE_ID, true)
{
    MOVEMENT_HILOGD(MOVEMENT_MODULE_SERVICE, "Add SystemAbility");
}

MovementService::~MovementService() {}

void MovementService::OnDump()
{
    MOVEMENT_HILOGD(MOVEMENT_MODULE_SERVICE, "OnDump");
}

void MovementService::OnStart()
{
    MOVEMENT_HILOGI(MOVEMENT_MODULE_SERVICE, "Enter");
    if (ready_) {
        MOVEMENT_HILOGE(MOVEMENT_MODULE_SERVICE, "OnStart is ready, nothing to do.");
        return;
    }

    if (!Init()) {
        MOVEMENT_HILOGE(MOVEMENT_MODULE_SERVICE, "OnStart call init fail");
        return;
    }
    if (!Publish(DelayedSpSingleton<MovementService>::GetInstance())) {
        MOVEMENT_HILOGE(MOVEMENT_MODULE_SERVICE, "OnStart register to system ability manager failed");
        return;
    }
    ready_ = true;

    MOVEMENT_HILOGI(MOVEMENT_MODULE_SERVICE, "OnStart and add system ability success");
}

void MovementService::OnStop()
{
    MOVEMENT_HILOGI(MOVEMENT_MODULE_SERVICE, "Enter");
    if (!ready_) {
        return;
    }
    ready_ = false;

    if (!movementManager_) {
        movementManager_->UnloadAlgorithm(false);
        MOVEMENT_HILOGE(MOVEMENT_MODULE_SERVICE, "unload algorithm library");
    }

    MOVEMENT_HILOGI(MOVEMENT_MODULE_SERVICE, "Exit");
}

bool MovementService::Init()
{
    MOVEMENT_HILOGI(MOVEMENT_MODULE_SERVICE, "Enter");

    if (!movementManager_) {
        movementManager_ = std::make_shared<MovementManager>(ms);
    }
    if (!movementManager_->Init()) {
        MOVEMENT_HILOGE(MOVEMENT_MODULE_SERVICE, "OnStart init fail");
        return false;
    }

    if (!movementStatistics_) {
        movementStatistics_ = std::make_shared<MovementStatistics>(ms);
    }

    if (!movementStatistics_->Init()) {
        MOVEMENT_HILOGE(MOVEMENT_MODULE_SERVICE, "OnStart init fail");
        return false;
    }
    return true;
}

bool MovementService::IsServiceReady()
{
    return ready_;
}

std::shared_ptr<MovementStatistics> MovementService::GetMovementStatistics()
{
    return movementStatistics_;
}

std::shared_ptr<MovementManager> MovementService::GetMovementManager()
{
    return movementManager_;
}

void MovementService::Subscribe(const MovementDataUtils::MovementType& type,
    const sptr<ImovementCallback>& callback)
{
    MOVEMENT_HILOGE(MOVEMENT_MODULE_SERVICE, "enter");
    movementManager_->Subscribe(type, callback);
    MOVEMENT_HILOGE(MOVEMENT_MODULE_SERVICE, "exit");
}

void MovementService::UnSubscribe(const MovementDataUtils::MovementType& type,
    const sptr<ImovementCallback>& callback)
{
    MOVEMENT_HILOGE(MOVEMENT_MODULE_SERVICE, "enter");
    movementManager_->UnSubscribe(type, callback);
    MOVEMENT_HILOGE(MOVEMENT_MODULE_SERVICE, "exit");
}

MovementDataUtils::MovementData MovementService::GetCache(const MovementDataUtils::MovementType& type)
{
    MOVEMENT_HILOGI(MOVEMENT_MODULE_SERVICE, "Service Enter");
    return movementManager_->GetLatestMovementData(type);
}

int32_t MovementService::Dump(int32_t fd, const std::vector<std::u16string> &args)
{
    MOVEMENT_HILOGI(MOVEMENT_MODULE_SERVICE, "enter");
    MovementDump &movementDump = MovementDump::GetInstance();
    if ((args.empty()) || (args[0].size() != MAX_DMUP_PARAM)) {
        MOVEMENT_HILOGE(MOVEMENT_MODULE_SERVICE, "param cannot be empty or the length is not 2");
        dprintf(fd, "cmd param number is not equal to 2\n");
        movementDump.DumpHelp(fd);
        return -1;
    }
    bool helpRet = movementDump.DumpMovementHelp(fd, args);
    bool total = helpRet;
    if (!total) {
        dprintf(fd, "cmd param is error\n");
        movementDump.DumpHelp(fd);
        return -1;
    }
    MOVEMENT_HILOGI(MOVEMENT_MODULE_SERVICE, "exit");
    return 0;
}
} // namespace Msdp
} // namespace OHOS
